-
Notifications
You must be signed in to change notification settings - Fork 61
GSoC 2025 blog on the ABI lowering library #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@nikic Will you please review content-wise? Thanks! |
@nikic ping :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not reviewing this earlier, I left some comments now.
As a high level note, I think that for the broader audience of a blog post we should probably focus more on the higher level stuff (concepts, design etc) than code snippets. No really specific suggestions on that though.
|
||
# Introduction | ||
|
||
In this post I'm going to outline details about a new ABI lowering library I've been developing for LLVM as part of GSoC 2025!. The aim was to extract the ABI logic from clang and create a reusable library that any LLVM frontend can use for correct C interoperability. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this post I'm going to outline details about a new ABI lowering library I've been developing for LLVM as part of GSoC 2025!. The aim was to extract the ABI logic from clang and create a reusable library that any LLVM frontend can use for correct C interoperability. | |
In this post I'm going to outline details about a new ABI lowering library I've been developing for LLVM as part of GSoC 2025! The aim was to extract the ABI logic from clang and create a reusable library that any LLVM frontend can use for correct C interoperability. |
|
||
Here's what that looks like in practice: | ||
```cpp | ||
struct Point { double x, y; }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
struct Point { double x, y; }; | |
struct Point { float x, y; }; |
I found that using float here makes things even more fun :) This godbolt shows that we end up using 6 different calling conventions on 6 different targets: https://clang.godbolt.org/z/P4fMj7hjY Maybe we can link it somewhere.
- Does x86-64 pass this in registers or memory? | ||
- What about ARM? PowerPC? WebAssembly? | ||
- Should it be scalarized to `(double, double, double, double)`? | ||
- Or does it need a hidden return parameter? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Does x86-64 pass this in registers or memory? | |
- What about ARM? PowerPC? WebAssembly? | |
- Should it be scalarized to `(double, double, double, double)`? | |
- Or does it need a hidden return parameter? | |
- Are the struct arguments passed in registers or memory? | |
- If in registers, what register class is used? | |
- Are multiple values packed into a single register? | |
- Is the struct returned in registers or using a hidden return parameter? |
I'd focus on just the different options here and leave that this is target-dependent to the next sentence.
- Should it be scalarized to `(double, double, double, double)`? | ||
- Or does it need a hidden return parameter? | ||
|
||
The answer depends on subtle ABI rules that are target-specific, constantly evolving, and absolutely critical to get right. Miss one detail and you get silent memory corruption that only shows up in release builds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The answer depends on subtle ABI rules that are target-specific, constantly evolving, and absolutely critical to get right. Miss one detail and you get silent memory corruption that only shows up in release builds. | |
The answer depends on subtle ABI rules that are target-specific, constantly evolving, and absolutely critical to get right. Miss one detail and you get silent memory corruption. |
ABI mismatches typically also show up in non-release builds.
# The Design | ||
|
||
<div style="margin:0 auto;"> | ||
<img src="/img/abi_flow.png"><br/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you still have the original around, I'd consider dropping the "register allocator" box. I know what you mean, but it's probably not what people expect when they see the term.
Not really important though, leave it alone if changing the image is a hassle.
|
||
# Results | ||
|
||
The library and the new typesystem are now successfully integrated into Clang, as part of the PR, and are enabled for BPF and X86-64 Linux targets. Here's what we achieved: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly to above, the wording here isn't super clear on this still being in a PR rather than integrated in upstream Clang.
|
||
``` | ||
Compare this to the old approach where BPF ABI logic would be scattered across multiple files, mixed with Clang-specific assumptions! | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think one bit that's missing here is how these results get back into Clang, i.e. the ABITypeMapper and that we populate the old Clang structs from the new ABI structs so both style are supported at the same time.
<img src="/img/abi_library_benchmarks.png"><br/> | ||
</div> | ||
|
||
The results are encouraging. Most compilation stages show essentially no performance difference (well within measurement noise). The 0.20% regression in the final Clang binary size is expected - we've added new code to the codebase. But the actual compilation performance impact is negligible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 0.20 number is is not a change in Clang binary size, but in time to build Clang (but the rest of what you say of course still applies).
|
||
# Future Work | ||
|
||
There's still plenty to explore: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd also add upstreaming here. Can also link to the PR you opened then.
|
||
## Extended Target Support | ||
|
||
Currently supporting BPF and X86-64 SysV, but the architecture makes adding ARM, Windows calling conventions, and other targets straightforward. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently supporting BPF and X86-64 SysV, but the architecture makes adding ARM, Windows calling conventions, and other targets straightforward. | |
Currently the ABI library supports the BPF and X86-64 SysV ABIs, but the architecture makes adding ARM, Windows calling conventions, and other targets straightforward. |
CC: @asl